const moment = require('moment');

const JiraModel = require('../Models/JiraModel');

const TimeTool = require('../Tools/TimeTool');
const JiraTool = require('../Tools/JiraTool');

const Pool = require('../Tools/Pool');

const LogService = require('./LogService');

class JiraService {
  
  /**
   * 返回Jira相关数据总览
   */
  async pandect() {
    let ret = await JiraModel.getJiraSql();

    if (ret.id) {
      delete ret.id;
    };
    return ret;
  };

  /**
   * 从Jira服务器中获取数据，并保存到数据库
   */
  async run() {
    await savePandectToSql();
  };

};


async function savePandectToSql() {
  let jiraData = {};
  LogService.info('Start');

  jiraData.bugTotal = await getBugTotal();
  LogService.info('BugTotal');

  jiraData.bugNumWeekGrowth = await getBugNumWeekGrowth();
  LogService.info('BugNumWeekGrowth');

  jiraData.bugNumDayGrowth = await getBugNumDayGrowth();
  LogService.info('BugNumDayGrowth');

  jiraData.bugDayAverage = await getBugDayAverage(jiraData.bugTotal);
  LogService.info('BugDayAverage');

  jiraData.bugMonthDetail = await getBugMonthDetail();
  LogService.info('BugMouthDetail');

  jiraData.bugMonthTotal = await getBugMonthTotal(jiraData.bugMonthDetail);
  LogService.info('BugMonthTotal');

  jiraData.bugMonthMax = await getBugMonthMax(jiraData.bugMonthDetail);
  LogService.info('BugMonthMax');

  jiraData.bugHandingRate = await getBugHandingRate(jiraData.bugTotal);
  LogService.info('BugHandingRate');

  jiraData.bugHandingWeekGrowth = await getBugHandingWeekGrowth();
  LogService.info('BugHandingWeekGrowth');

  jiraData.bugHandingDayGrowth = await getBugHandingDayGrowth();
  LogService.info('BugHandingDayGrowth');

  jiraData.bugModel = await getBugModle();
  LogService.info('BugModel');

  jiraData.bugProjectTotal = await getBugProjectTotal();
  LogService.info('BugProjectTotal');

  jiraData.bugProjectHandUp = await getBugProjectHandUp(jiraData.bugHandingRate);
  LogService.info('BugProjectHandUp');

  jiraData.bugProjectTrend = await getBugProjectTrend();
  LogService.info('BugProjectTrend');

  await JiraModel.saveToSql(jiraData);
  LogService.info('Saving');
};

async function getBugTotal() {
  let res = await JiraModel.getBugByJql();
  let ret = res.total;
  return ret;
};

async function getBugNumWeekGrowth() {
  let ret = 0;
  let oneWeek = await JiraModel.getBugByJql({ jql: 'created >= -1w' });
  let twoWeek = await JiraModel.getBugByJql({ jql: 'created >= -2w' });
  let prev = twoWeek.total - oneWeek.total;
  let next = oneWeek.total;
  if (prev !== 0) {
    ret = (next - prev) / prev;
  };
  return ret;
};

async function getBugNumDayGrowth() {
  let ret = 0;
  let oneDay = await JiraModel.getBugByJql({ jql: 'created >= -1d' });
  let twoDay = await JiraModel.getBugByJql({ jql: 'created >= -2d' });
  let prev = twoDay.total - oneDay.total;
  let next = oneDay.total;
  if (prev !== 0) {
    ret = (next - prev) / prev;
  };
  return ret;
};

async function getBugDayAverage(data) {
  let days = TimeTool.getDays('2016/01/15');
  let ret = data / days;
  return ret;
};

async function getBugMonthTotal(data) {
  let sum = 0;
  for (let i in data) {
    sum += data[i].y;
  };
  return sum;
};

async function getBugMonthDetail() {
  let ret = [];
  let now = new Date().getTime();
  for (let i = 0; i < 30; i++) {
    let nowDate = TimeTool.getDate(29 - i);
    let nextDate = TimeTool.getDate(28 - i);
    let res = await JiraModel.getBugByJql({ jql: `created >= ${nowDate} AND created <= ${nextDate}` });
    ret.push({
      x: nowDate,
      y: res.total
    });
  };
  return ret;
};

async function getBugMonthMax(data) {
  let max = 0;
  for (let i in data) {
    if (data[i].y > max) {
      max = data[i].y;
    };
  };
  return max;
};

async function getBugHandingRate(data) {
  let ret = 0;
  let res = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7' })
  if (data !== 0) {
    ret = res.total / data;
  }
  return ret;
}

async function getBugHandingWeekGrowth() {
  let ret = 0;
  let oneWeek = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7 AND created >= -1w' });
  let twoWeek = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7 AND created >= -2w' });
  let prev = twoWeek.total - oneWeek.total;
  let next = oneWeek.total;
  if (prev !== 0) {
    ret = (next - prev) / prev;
  };
  return ret;
}

async function getBugHandingDayGrowth() {
  let ret = 0;
  let oneDay = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7 AND created >= -1d' });
  let twoDay = await JiraModel.getBugByJql({ jql: 'status = %e6%8c%82%e8%b5%b7 AND created >= -2d' });
  let prev = twoDay.total - oneDay.total;
  let next = oneDay.total;
  if (prev !== 0) {
    ret = (next - prev) / prev;
  };
  return ret;
}

async function getBugModle() {
  let projArray = [];
  let projects = await JiraModel.getProjectById();
  for (let i in projects) {
    let { id, key, name } = projects[i];
    let components = await getComponents(id, key);
    projArray.push({
      projectName: name,
      data: components,
    });
  };
  let ret = getAllProject(projArray);
  return ret;
};

function getAllProject(arr) {
  let allData = [];
  let ret = arr;
  for (let i in arr) {
    if (arr[i].data) {
      for (let j in arr[i].data) {
        allData.push(arr[i].data[j])
      };
    };
  };
  let retData = JiraTool.sortByKey(allData, 'count');
  for (let i in retData) {
    retData[i].index = parseInt(i) + 1;
  };
  ret.unshift({ projectName: '全部项目', data: retData });
  return ret;
}

async function getComponents(projectId, projectKey) {
  let ret = [];
  let { components } = await JiraModel.getProjectById(projectId);
  if (components) {
    for (let j in components) {
      let { id, name } = components[j];
      let component = await JiraModel.getBugByJql({ jql: `project = ${projectKey} AND component = ${id}` });
      let count = component.total;
      let growth = await getVersionGrowth(projectId, projectKey, id);
      ret.push({
        index: 0,
        model: name,
        count,
        growth,
      });
    };
    ret = JiraTool.sortByKey(ret, 'count');
  };
  return ret;
};

async function getVersionGrowth(projectId, projectKey, componentId) {
  let ret = 0;
  let versions = await JiraModel.getProjectVersionsById(projectId);
  if (versions && versions.length > 1) {
    let latestVersion = versions[versions.length - 1].id;
    let prevVersion = versions[versions.length - 2].id;
    let latestJql = `project = ${projectKey} AND affectedVersion = ${latestVersion} AND component = ${componentId}`;
    let prevJql = `project = ${projectKey} AND affectedVersion = ${prevVersion} AND component = ${componentId}`;
    let latest = await JiraModel.getBugByJql({ jql: latestJql });
    let prev = await JiraModel.getBugByJql({ jql: prevJql });
    if (prev.total !== 0) {
      ret = (latest.total - prev.total) / prev.total;
    };
  };
  return ret;
};

async function getBugProjectTotal() {
  let ret = [];
  let projects = await JiraModel.getProjectById();
  for (let i in projects) {
    let { id, name } = projects[i];
    let projectBug = await JiraModel.getBugByJql({ jql: `project = ${id}` });
    let { total } = projectBug;
    ret.push({ x: name, y: total });
  };
  ret = JiraTool.sortByKey(ret, 'y');
  return ret;
};

async function getBugProjectHandUp(rate) {
  let ret = [];
  let projects = await JiraModel.getProjectById();
  for (let i in projects) {
    let handingRate = 0;
    let { id, name } = projects[i];
    let projectBug = await JiraModel.getBugByJql({ jql: `project = ${id}` });
    let { total } = projectBug;
    let projectHandUp = await JiraModel.getBugByJql({ jql: `project = ${id} AND status = %e6%8c%82%e8%b5%b7` });
    if (total !== 0) {
      handingRate = projectHandUp.total / total;
    };
    ret.push({ projectName: name, handingRate });
  };
  ret.unshift({ projectName: '全部项目', handingRate: rate });
  return ret;
};

async function getBugProjectTrend() {
  let ret = [];
  let projects = await JiraModel.getProjectById();
  for (let i in projects) {
    let { id, name } = projects[i];
    ret.push({ projectId: id, projectName: name, data: [] });
  };
  await setProjectData(ret);
  await setAllProlectData(ret);
  return ret;
};

async function setAllProlectData(arr) {
  let now = new Date().getTime();
  arr.unshift({ projectName: '全部项目', data: [] });
  for (let i = 0; i < 30; i++) {
    let nowDate = TimeTool.getDate(29 - i);
    let nextDate = TimeTool.getDate(28 - i);
    let newBug = await JiraModel.getBugByJql({
      jql: `created >= ${nowDate} AND created <= ${nextDate}`
    });
    let fixBug = await JiraModel.getBugByJql({
      jql: `status in (%e5%b7%b2%e8%a7%a3%e5%86%b3, %e9%97%ae%e9%a2%98%e5%85%b3%e9%97%ad)
        AND updated >= ${nowDate} AND updated <= ${nextDate}`
    });
    let handupBug = await JiraModel.getBugByJql({
      jql: `status = %e6%8c%82%e8%b5%b7 AND updated >= ${nowDate} AND updated <= ${nextDate}`
    });
    arr[0].data.push({
      x: now - (1000 * 60 * 60 * 24 * (29 - i)),
      y1: newBug.total,
      y2: fixBug.total,
      y3: handupBug.total
    });
  };
};

async function setProjectData(projects) {
  let now = new Date().getTime();
  for (let k in projects) {
    for (let i = 0; i < 30; i++) {
      let nowDate = TimeTool.getDate(29 - i);
      let nextDate = TimeTool.getDate(28 - i);
      let newBug = await JiraModel.getBugByJql({
        jql: `project = ${projects[k].projectId} AND created >= ${nowDate} AND created <= ${nextDate}`
      });
      let fixBug = await JiraModel.getBugByJql({
        jql: `project = ${projects[k].projectId} AND status in (%e5%b7%b2%e8%a7%a3%e5%86%b3, %e9%97%ae%e9%a2%98%e5%85%b3%e9%97%ad)
          AND updated >= ${nowDate} AND updated <= ${nextDate}`
      });
      let handupBug = await JiraModel.getBugByJql({
        jql: `project = ${projects[k].projectId} AND status = %e6%8c%82%e8%b5%b7 AND updated >= ${nowDate} AND updated <= ${nextDate}`
      });
      projects[k].data.push({
        x: now - (1000 * 60 * 60 * 24 * (29 - i)),
        y1: newBug.total,
        y2: fixBug.total,
        y3: handupBug.total
      });
    };
  };
};

module.exports = new JiraService();